import java.util.ArrayList;

import ncsa.hdf.hdf5lib.H5;
import ncsa.hdf.hdf5lib.HDF5Constants;
import ncsa.hdf.hdf5lib.exceptions.HDF5Exception;
import ncsa.hdf.hdf5lib.exceptions.HDF5LibraryException;


public class EspacioDeEstados {
	public static ArrayList<Estado> Sucesor (Estado e){	
		
		ArrayList <Estado> sucesores= new ArrayList<Estado>();
		
		String hoja= e.getLugarGeografico().getNombre();
		int x= e.getLugarGeografico().getX();
		int y= e.getLugarGeografico().getY();
		
		int matrizAtributos[]= leerAtributos(hoja);
		
		//NORTE: obtenemos las coordenadas UMT restandole 1 la coordenada Y
		// Con las nuevas coordeandas UMT obtenemos el lugar geografico que sera el sucesor
		if ((x >= 0 && x < matrizAtributos[1]) && (y-1 >=  0 && y-1 < matrizAtributos[0])){
			float altitud= UTIL.Altitud(hoja, x, y-1);
			posicionActual p1= new posicionActual(hoja, x, y-1);
			Estado e1= new Estado (p1, altitud, "S");
			sucesores.add(e1);
		}
		else{
			posicionActual p1= UTIL.UMT(hoja,x, y-1);
			posicionActual p2= UTIL.LugarGeografico(p1.getX(), p1.getY());
			if (p2 != null){
				float altitud= UTIL.Altitud(p2.getNombre(), p2.getX(), p2.getY());
				Estado e1= new Estado (p2, altitud, "S");
				sucesores.add(e1);
			}
			
		}
		
		//SUR: obtenemos las coordenadas UMT sumandole 1 la coordenada Y
		// Con las nuevas coordeandas UMT obtenemos el lugar geografico que sera el sucesor
		if ((x >= 0 && x < matrizAtributos[1]) && (y+1 >=  0 && y+1 < matrizAtributos[0])){
			float altitud= UTIL.Altitud(hoja, x, y+1);
			posicionActual p1= new posicionActual(hoja, x, y+1);
			Estado e1= new Estado (p1, altitud, "N");
			sucesores.add(e1);
		}
		else{
			posicionActual p1= UTIL.UMT(hoja,x, y+1);
			posicionActual p2= UTIL.LugarGeografico(p1.getX(), p1.getY());
			if (p2 != null){
				float altitud= UTIL.Altitud(p2.getNombre(), p2.getX(), p2.getY());
				Estado e1= new Estado (p2, altitud, "N");
				sucesores.add(e1);
			}
		}
		
		//ESTE: obtenemos las coordenadas UMT sumandole 1 la coordenada X
		// Con las nuevas coordeandas UMT obtenemos el lugar geografico que sera el sucesor
		if ((x+1 >= 0 && x+1 < matrizAtributos[1]) && (y >=  0 && y < matrizAtributos[0])){
			float altitud= UTIL.Altitud(hoja, x+1, y);
			posicionActual p1= new posicionActual(hoja, x+1, y);
			Estado e1= new Estado (p1, altitud, "O");
			sucesores.add(e1);
		}
		else{
			posicionActual p1= UTIL.UMT(hoja,x+1, y);
			posicionActual p2= UTIL.LugarGeografico(p1.getX(), p1.getY());
			if (p2 != null){
				float altitud= UTIL.Altitud(p2.getNombre(), p2.getX(), p2.getY());
				Estado e1= new Estado (p2, altitud, "O");
				sucesores.add(e1);
			}
		}
		
		//OESTE: obtenemos las coordenadas UMT restandole 1 la coordenada X
		// Con las nuevas coordeandas UMT obtenemos el lugar geografico que sera el sucesor
		if ((x-1 >= 0 && x-1 < matrizAtributos[1]) && (y >=  0 && y < matrizAtributos[0])){
			float altitud= UTIL.Altitud(hoja, x-1, y);
			posicionActual p1= new posicionActual(hoja, x-1, y);
			Estado e1= new Estado (p1, altitud, "E");
			sucesores.add(e1);
		}
		else{
			posicionActual p1= UTIL.UMT(hoja,x-1, y);
			posicionActual p2= UTIL.LugarGeografico(p1.getX(), p1.getY());
			if (p2 != null){
				float altitud= UTIL.Altitud(p2.getNombre(), p2.getX(), p2.getY());
				Estado e1= new Estado (p2, altitud, "E");
				sucesores.add(e1);
			}
		}
		
		//NORESTE: obtenemos las coordenadas UMT sumandole 1 la coordenada X y restandole 1 a Y
		// Con las nuevas coordeandas UMT obtenemos el lugar geografico que sera el sucesor
		if ((x+1 >= 0 && x+1 < matrizAtributos[1]) && (y-1 >=  0 && y-1 < matrizAtributos[0])){
			float altitud= UTIL.Altitud(hoja, x+1, y-1);
			posicionActual p1= new posicionActual(hoja, x+1, y-1);
			Estado e1= new Estado (p1, altitud, "SO");
			sucesores.add(e1);
		}
		else{
			posicionActual p1= UTIL.UMT(hoja,x+1, y-1);
			posicionActual p2= UTIL.LugarGeografico(p1.getX(), p1.getY());
			if (p2 != null){
				float altitud= UTIL.Altitud(p2.getNombre(), p2.getX(), p2.getY());
				Estado e1= new Estado (p2, altitud, "SO");
				sucesores.add(e1);
			}
		}
		
		//NOROESTE: obtenemos las coordenadas UMT restandole 1 la coordenada X y restandole 1 a Y
		// Con las nuevas coordeandas UMT obtenemos el lugar geografico que sera el sucesor
		if ((x-1 >= 0 && x-1 < matrizAtributos[1]) && (y-1 >=  0 && y-1 < matrizAtributos[0])){
			float altitud= UTIL.Altitud(hoja, x-1, y-1);
			posicionActual p1= new posicionActual(hoja, x-1, y-1);
			Estado e1= new Estado (p1, altitud, "SE");
			sucesores.add(e1);
		}
		else{
			posicionActual p1= UTIL.UMT(hoja,x-1, y-1);
			posicionActual p2= UTIL.LugarGeografico(p1.getX(), p1.getY());
			if (p2 != null){
				float altitud= UTIL.Altitud(p2.getNombre(), p2.getX(), p2.getY());
				Estado e1= new Estado (p2, altitud, "SE");
				sucesores.add(e1);
			}
		}
		
		//SURESTE: obtenemos las coordenadas UMT sumandole 1 la coordenada X y sumandole 1 a Y
		// Con las nuevas coordeandas UMT obtenemos el lugar geografico que sera el sucesor
		if ((x+1 >= 0 && x+1 < matrizAtributos[1]) && (y+1 >=  0 && y+1 < matrizAtributos[0])){
			float altitud= UTIL.Altitud(hoja, x+1, y+1);
			posicionActual p1= new posicionActual(hoja, x+1, y+1);
			Estado e1= new Estado (p1, altitud, "NO");
			sucesores.add(e1);
		}
		else{
			posicionActual p1= UTIL.UMT(hoja,x+1, y+1);
			posicionActual p2= UTIL.LugarGeografico(p1.getX(), p1.getY());
			if (p2 != null){
				float altitud= UTIL.Altitud(p2.getNombre(), p2.getX(), p2.getY());
				Estado e1= new Estado (p2, altitud, "NO");
				sucesores.add(e1);
			}
		}
		
		//SUROESTE: obtenemos las coordenadas UMT restandole 1 la coordenada X y sumandole 1 a Y
		// Con las nuevas coordeandas UMT obtenemos el lugar geografico que sera el sucesor
		if ((x-1 >= 0 && x-1 < matrizAtributos[1]) && (y+1 >=  0 && y+1 < matrizAtributos[0])){
			float altitud= UTIL.Altitud(hoja, x-1, y+1);
			posicionActual p1= new posicionActual(hoja, x-1, y+1);
			Estado e1= new Estado (p1, altitud, "NE");
			sucesores.add(e1);
		}
		else{
			posicionActual p1= UTIL.UMT(hoja,x-1, y+1);
			posicionActual p2= UTIL.LugarGeografico(p1.getX(), p1.getY());
			if (p2 != null){
				float altitud= UTIL.Altitud(p2.getNombre(), p2.getX(), p2.getY());
				Estado e1= new Estado (p2, altitud, "NE");
				sucesores.add(e1);
			}
		}
		
		return sucesores;
	}
	
	public static int[] leerAtributos (String nombre){
		int dataset_id= -1;
		int attribute_id= -1;
		int matriz[]= new int[9];
		
        
        // Abrir dataset
        try {
        	if (UTIL.file_id >= 0)
        		dataset_id= H5.H5Dopen(UTIL.file_id, "/" + nombre, HDF5Constants.H5P_DEFAULT);
        }
        catch (Exception e) {
        	e.printStackTrace();
        }
        
        // Abrir atributos
        try {
        	if (dataset_id >= 0)
        		attribute_id = H5.H5Aopen(dataset_id, UTIL.DATASETATTRIBUTE, HDF5Constants.H5P_DEFAULT);
        }
        catch (Exception e) {
        	e.printStackTrace();
        }
  	  	
        // Leer atributos y guardalos en matriz, los sacamos para obtener el tama�o de la matriz de datos.
        try {
			H5.H5Aread(attribute_id, HDF5Constants.H5T_NATIVE_INT, matriz);
        } catch (NullPointerException | HDF5Exception e) {
			e.printStackTrace();
        }
        
        // Cerrar los atributos.
        try {
        	if (attribute_id >= 0)
        		H5.H5Aclose(attribute_id);
        }
        catch (Exception e) {
        	e.printStackTrace();
        }
        
        // Cerrar el dataset.
  		try {
  			if (dataset_id >= 0)
  				H5.H5Dclose(dataset_id);
  		}
  		catch (Exception e) {
  			e.printStackTrace();
  		}	
        
  		return matriz;
	}
}